﻿using System.Globalization;

namespace CyberConnect.Insteon.Messaging
{
    /// <summary>
    /// Encapsulates a PLM message sent to or received from an INSTEON responder.
    /// </summary>
    [System.ComponentModel.ImmutableObject(true)]
    public class DeviceMessage : IMessage
    {
        private readonly DeviceAddress _Address;
        private readonly MessageConfiguration _Configuration;
        private readonly MessageCommand _Command;

        /// <summary>
        /// DeviceAddress to target.
        /// </summary>
        public DeviceAddress Address { get { return _Address; } }

        /// <summary>
        /// Configuration of the message.
        /// </summary>
        /// <seealso cref="MessageConfiguration"/>
        public MessageConfiguration Configuration { get { return _Configuration; } }

        /// <summary>
        /// The MessageCommand to send to a responder.
        /// </summary>
        public MessageCommand Command { get { return _Command; } }

        public DeviceMessage(DeviceAddress address, MessageConfiguration configuration, MessageCommand command, object userData = null)
        {
            this._Address = address;
            this._Configuration = configuration;
            this._Command = command;
        }

        private DeviceMessage()
        {
        }

        #region IMessage Members

        /// <summary>
        /// Breaks an IMessage into a byte array that the PLM understands.
        /// </summary>
        /// <returns>A byte array that the PLM understands</returns>
        public byte[] ToBytes()
        {
            byte[] MessageBytes = new byte[8];

            MessageBytes[0] = DeviceMessage.StartByte;
            MessageBytes[1] = (byte)PlmCommand.SendMessage;
            MessageBytes[2] = Address.High;
            MessageBytes[3] = Address.Middle;
            MessageBytes[4] = Address.Low;
            MessageBytes[5] = (byte)((byte)Configuration | 0x0F);
            MessageBytes[6] = Command.Command1;
            MessageBytes[7] = Command.Command2;

            return MessageBytes;
        }

        #endregion IMessage Members

        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentCulture, "[{0}] {1} [{2}]", this.Address, this.Configuration.ToInt32().ToString("X4", CultureInfo.CurrentCulture), this.Command);
        }

        public const byte StartByte = 0x02;

        public static int ReceivedMessageLength(bool isExtended)
        {
            return (isExtended) ? 25 : 11;
        }
    }
}